home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 142 / Gekkan Dennou Club - 2000.3 Vol. 142 (Japan).7z / Gekkan Dennou Club - 2000.3 Vol. 142 (Japan) (Track 1).bin / imelo / cmscc / cmscc.c next >
C/C++ Source or Header  |  2000-02-06  |  11KB  |  566 lines

  1. /*
  2. 着メロコンパイラ@@
  3.  
  4.     *.cms → 何等かのテキスト
  5. */
  6.  
  7. #include    <stdio.h>
  8.  
  9. extern    int    CMSCC_conv23_F502i();
  10. extern    int    CMSCC_conv23_P501i();
  11. extern    int    CMSCC_conv23_HDGE_J80();
  12. extern    int    CMSCC_conv23_SH811();
  13.  
  14.  
  15. int    Telephone;    //電話機の種類
  16. typedef    enum{
  17.     F502I,        //iMODE
  18.     P501I,
  19.     N501I,    //@@まだ
  20.     D501I,    //@@まだ
  21.  
  22.     HDGE_J80,    //H"(SANYO PHS-J80)
  23.     SH811        //ドッチーモ(SHARP SH811)
  24. } TELEPHONE;
  25.  
  26. /*
  27.     共通設定項目
  28. */
  29. int    nowLen=4;            //音長(デフォルト=4)
  30. int    nowOct=4;            //オクターブ(デフォルト=4)
  31. int    nowKsignS=0,nowKsignF=0;    //調号の設定
  32.                     //0cdefgab 
  33.                     // +++++++--1=ON/0=OFF
  34.  
  35. #define    BUFSIZE    (256)            //*.cms1行あたりのサイズ
  36. unsigned char    inBuf[BUFSIZE],        //ファイル読み込みバッファ
  37.         tmpBuf[BUFSIZE*16],    //1→2変換バッファ
  38.         outBuf[BUFSIZE*16],    //2→3出力バッファ
  39.         mesBuf[BUFSIZE];    //エラーメッセージなど
  40.  
  41.  
  42. const    unsigned char *errMes[]={    //エラーメッセージいろいろ
  43.     NULL,
  44.     "Lnの値が異常です",
  45.     "Onの値が異常です"
  46. };
  47. enum    {
  48.     noErr,
  49.     L_NUMBER_ERR,
  50.     O_NUMBER_ERR,
  51. } errNum;
  52.  
  53.  
  54.  
  55.  
  56. /*
  57.     Ln(有効n値:1,2,4.,4,8.,8,16)のチェックおよびnowLenの設定
  58.     
  59.     res:s0を基準に、読み進めるカウント数(0以下でエラー)
  60. */
  61. int    L_Check(s0,s1,s2,s3)
  62. unsigned char    s0,s1,s2,s3;    //s0=='L'の状態で呼び出される
  63. {
  64.     int    step=2;
  65.     short    futen2=(s2=='.')?1:0;
  66.  
  67.     switch( s1 ){
  68.         case '1':
  69.             if( s2=='6' ){
  70.                 nowLen=16;
  71.                 step=3;
  72.             }
  73.             else if( s2=='2' ){
  74.                 nowLen=12;
  75.                 step=3;
  76.             }
  77.             else{    //L1?の時は、Lでエラーとしない
  78.                 nowLen=1;
  79.             }
  80.         break;
  81.         case '2': nowLen=2;        break;
  82.         case '3': nowLen=3;        break;
  83.         case '4':            //符点4分かどうか
  84.             if( futen2 ){    nowLen=3;    step++;        }
  85.             else{        nowLen=4;            }
  86.         break;
  87.         case '6': nowLen=6;        break;
  88.         case '8':            //符点8分かどうか
  89.             if( futen2 ){    nowLen=6;    step++;        }
  90.             else{        nowLen=8;            }
  91.         break;
  92.         default:
  93.             step=-1;
  94.         break;
  95.     }
  96.  
  97.     return(step);
  98. }
  99.  
  100.  
  101.  
  102. /*
  103.     On(有効n値:3~5)のチェックおよびnowOctの設定
  104.     
  105.     res:s0を基準に、読み進めるカウント数==2(0以下でエラー)
  106. */
  107. int    O_Check(s0,s1)
  108. unsigned char    s0,s1;    //s0=='O'の状態で呼び出される
  109. {
  110.     int    step=2;
  111.  
  112.     switch( s1 ){
  113.         case '3': case '4': case '5':
  114.             nowOct=s1-'0';
  115.         break;
  116.         default:
  117.             step=-1;
  118.         break;
  119.     }
  120.  
  121.     return(step);
  122. }
  123.  
  124.  
  125.  
  126.  
  127. /*
  128.     MMLのチェック
  129.     outに変換後のMMLを入れる
  130.  
  131. 出力形態は、
  132.  
  133.     On?fl   
  134.      |||+-音長('1','2','3','4','6','8',12='C',16='H')
  135.      ||+--#フラグ('+'or'0'なし)
  136.      |+---音名('C','D','E','F','G','A','B'or'R')
  137.      +----オクターブ('3','4','5')
  138.  
  139. を一応。保証。
  140. 趣味の問題で、後ろに' '($20)を3ついれて、8バイト1組みにする
  141.  
  142. */
  143. int    MML_Check(out,s0,s1,s2,s3)
  144. unsigned char    *out;
  145. unsigned char    s0,s1,s2,s3;
  146. {
  147.     int    step=0;
  148.     unsigned char *o=out;
  149.  
  150.     char    skip=0;            //MML出力スキップする(1)/しない(0)/それ以外
  151.     unsigned char name=0;        //音階
  152.     char sharp_flat=0;        //#+(=+1)-(=-1)つきか
  153.     unsigned char len=0;        //音長が指定されているか
  154.     unsigned char add[16];
  155.     unsigned char s[4],*sp;
  156.  
  157.     s[0]=s0;s[1]=s1;s[2]=s2;s[3]=s3;
  158.     sp=s;
  159.     
  160.     /*    解析
  161.     */
  162.     switch( *sp ){
  163.         case 'c': case 'C':
  164.         case 'd': case 'D':
  165.         case 'e': case 'E':
  166.         case 'f': case 'F':
  167.         case 'g': case 'G':
  168.         case 'a': case 'A':
  169.         case 'b': case 'B':
  170.             switch( *(sp+1) ){
  171.                 case '#': case '+':    name=*sp++;    sharp_flat=1;    sp++;    step++;    goto skip_r;    break;
  172.                 case '-':        name=*sp++;    sharp_flat=-1;    sp++;    step++;    goto skip_r;    break;
  173.             }
  174.         case 'r': case 'R':    //休符
  175.             name=*sp++;
  176. skip_r:
  177.             step++;
  178.             if( *sp=='1' ){
  179.                 if( *(sp+1)=='6' ){    len=16;    step++;    }
  180.                 else if( *(sp+1)=='2' ){len=12;    step++;    }
  181.                 else{            len=1;        }
  182.                 step++;
  183.             }
  184.             else if( *sp=='2' ){        len=2;    step++;    }
  185.             else if( *sp=='3' ){        len=3;    step++;    }
  186.             else if( *sp=='4' ){
  187.                 if( *(sp+1)=='.' ){    len=3;    step++;    }
  188.                 else{            len=4;        }
  189.                 step++;
  190.             }
  191.             else if( *sp=='6' ){        len=6;    step++;    }
  192.             else if( *sp=='8' ){
  193.                 if( *(sp+1)=='.' ){    len=6;    step++;    }
  194.                 else{            len=8;        }
  195.                 step++;
  196.             }
  197.         break;
  198.         
  199.         case '<':
  200.             nowOct++;
  201.             skip=1;
  202.             step++;
  203.             if( 5<nowOct ){
  204.                 step=-2;
  205.                 goto quick_exit;
  206.             }
  207.         break;
  208.         case '>':
  209.             nowOct--;
  210.             skip=1;
  211.             step++;
  212.             if( nowOct<3 ){
  213.                 step=-2;
  214.                 goto quick_exit;
  215.             }
  216.         break;
  217.  
  218.         /*    例外字スキップ関係
  219.         */
  220.         case '@':    //@@暫定「@n」のみ有効
  221.             skip=1;
  222.             step+=2;
  223.         break;
  224.  
  225.         /*    空文字スキップ関係
  226.         */
  227.         case ' ':
  228.         case 0x0d: case 0x0a: case '\t':/*改行系*/
  229.             skip=*sp;
  230.             step++;
  231.         break;
  232.  
  233.         default:
  234.             step=-1;
  235.             goto quick_exit;
  236.         break;
  237.     }
  238.  
  239.     /*    生成
  240.     */
  241.     *o=NULL;
  242.     if( skip==0 ){
  243.         if( 'a'<=name )name-=0x20;    //大文字化
  244.         if( sharp_flat==-1 ){
  245.             //レ♭→ド♯ な感じの変換
  246.             switch( name ){
  247.                 case 'D': name='C';    break;
  248.                 case 'E': name='D';    break;
  249.                 case 'G': name='F';    break;
  250.                 case 'A': name='G';    break;
  251.                 case 'B': name='A';    break;
  252.             }
  253.             sharp_flat=1;
  254.         }
  255.  
  256.         if( ((len)?len:nowLen)==16 ){
  257.             sprintf(add,"O%d%C%CH",nowOct,name,(sharp_flat==1)?'+':'0');
  258.         }
  259.         else if( ((len)?len:nowLen)==12 ){
  260.             sprintf(add,"O%d%C%CC",nowOct,name,(sharp_flat==1)?'+':'0');
  261.         }
  262.         else{
  263.             sprintf(add,"O%d%C%C%d",nowOct,name,(sharp_flat==1)?'+':'0',(len)?len:nowLen);
  264.         }
  265.         strcat(o,add);
  266.         strcat(o,"   ");    //隙間埋め
  267.     }
  268.     else if( skip!=1 ){    //単純スキップでなければ
  269. //        *o++=skip;
  270.         *o++=NULL;
  271.     }
  272.     
  273. quick_exit:
  274.     return(step);
  275. }
  276.  
  277.  
  278.  
  279.  
  280. typedef    enum{
  281.     NORMAL=0,        //通常終了
  282.     READ_REMARK=1,        //注釈行読み込み
  283.     READ_CRLF=2,        //改行読み込み
  284. } CONV12_RESULT;
  285. /*
  286.     *.cms → 中間コードへ
  287.  
  288.     res:
  289. */
  290. int    CMSCC_conv12(src,dest,err)
  291. unsigned char    *src,        //*.cms行
  292.         *dest,        //中間コード行
  293.         *err;        //エラーメッセージ
  294. {
  295.     int    res=NORMAL,step=0;
  296.     short    MUSHI=0;    //()は無視する:1=無視最中/0=無視してない
  297.     unsigned char    *s,*d,*e;
  298.     unsigned char    s0,s1,s2,s3;
  299.     
  300.     s=src;
  301.     d=dest;    *d=NULL;
  302.     e=err;
  303.  
  304.     //行頭注釈チェック
  305.     if( *s=='/' ){
  306.         res=READ_REMARK;
  307.         goto quick_exit;
  308.     }
  309.  
  310.     //行頭改行チェック
  311.     if( *s==0x0d || *s==0x0a  ){
  312.         res=READ_CRLF;
  313.         goto quick_exit;
  314.     }
  315.     
  316.     while( *s ){
  317.         s0=*s;s1=*(s+1);s2=*(s+2);s3=*(s+3);    //4バイト先行読み込み
  318.         //printf("[%c]",s0);
  319.         
  320.         /*
  321.             特殊文字・制御文字チェック
  322.         */
  323.         switch( s0 ){
  324.             /*    ()内無視チェック
  325.             */
  326.             case '(':
  327.                 MUSHI=1;    //無視開始
  328.                 goto next;
  329.             break;
  330.             case ')':
  331.                 if( MUSHI==1 ){
  332.                     MUSHI=0;    //無視解除
  333.                 }
  334.                 else{
  335.                     /*    @@未実装
  336.                         '('がないのに')'を指定したエラー
  337.                     */
  338.                 }
  339.                 goto next;
  340.             break;
  341.  
  342.             /*    '/'以降注釈チェック
  343.             */
  344.             case '/':        //'/'以降の行は無視して終わる
  345.                 res=NORMAL;
  346.                 goto quick_exit;
  347.             break;
  348.             
  349.         }
  350.  
  351.         if( MUSHI==0 ){ ; switch( s0 ){
  352.             /*
  353.                 共通設定のチェック
  354.             */
  355.             /*    音長
  356.             */
  357.             case 'l': case 'L':
  358.                 step=L_Check(s0,s1,s2,s3);
  359.                 if( step<0 ){
  360.                     res=-L_NUMBER_ERR;
  361.                     err=errMes[L_NUMBER_ERR];
  362.                     goto quick_exit;
  363.                 }
  364.                 s+=(step-1);
  365.             break;
  366.             
  367.             /*    オクターブ
  368.             */
  369.             case 'o': case 'O':
  370.                 step=O_Check(s0,s1);
  371.                 if( step<0 ){
  372.                     res=-O_NUMBER_ERR;
  373.                     err=errMes[O_NUMBER_ERR];
  374.                     goto quick_exit;
  375.                 }
  376.                 s+=(step-1);
  377.             break;
  378.             
  379.             /*
  380.                 MMLの解釈
  381.             */
  382.             default:{
  383.                 unsigned char    out[32];    //@@本当は8+1バイトでよい
  384.                 step=MML_Check(out,s0,s1,s2,s3);
  385.                 if( step>=0 ){
  386.                     /*    OK
  387.                     */
  388.                     s+=(step-1);
  389.                     strcat(d,out);
  390.                     ///**/printf("[%s]",out);
  391.                 }
  392.                 else{
  393.                     /*    ダメ
  394.                     */
  395.                     res=-O_NUMBER_ERR;    //@@暫定
  396.                     err=errMes[O_NUMBER_ERR];
  397.                     goto quick_exit;
  398.                 }
  399.             }break;
  400.         }}
  401. next:
  402.         s++;
  403.     }
  404.     
  405. quick_exit:
  406.     return(res);
  407.  
  408. }
  409.  
  410.  
  411.  
  412. /*    チェック用カタカナ変換
  413.  
  414.     位置合わせあり版
  415.     注意:おそらくこの仕様にそわない携帯電話はないと思うが、
  416.  
  417.         1 2 3    ド レ ミ
  418.         4 5 6    ファ ソ ラ
  419.         7 8 9    シ
  420.  
  421.     のみ有効
  422. */
  423. int    CMSCC_convKANA(src,dest,err)
  424. unsigned char    *src,*dest,*err;
  425. {
  426.     unsigned char    *s,*d,*e;
  427.     unsigned char    name0,name1;    //音名
  428.     unsigned char    skip;    //スキップコード
  429. enum{
  430.     SCH_NAME,    //音名('1'~'7')が出るまで探す
  431.     SCH_BOTM    //入力区切り('>')が出るまで探す
  432. } CND;
  433.     short    cnd=SCH_NAME;
  434.  
  435.     s=src;
  436.     d=dest;    *d=NULL;
  437.     e=err;
  438.  
  439.     while( *s ){
  440.         /*    読み込み
  441.         */
  442.         skip=0;
  443.         name0=0;
  444.         if( cnd==SCH_NAME ){
  445.             switch( *s ){
  446.                 case '1':    name0='ト';name1='゙';    break;
  447.                 case '2':    name0='レ';name1=' ';    break;
  448.                 case '3':    name0='ミ';name1=' ';    break;
  449.                 case '4':    name0='フ';name1='ァ';    break;
  450.                 case '5':    name0='ソ';name1=' ';    break;
  451.                 case '6':    name0='ラ';name1=' ';    break;
  452.                 case '7':    name0='シ';name1=' ';    break;
  453.                 case ' ': case 0x0d: case 0x0a: case '\t':
  454.                     skip=*s++;
  455.                 break;
  456.                 default:
  457.                     skip=' ';s++;
  458.                 break;
  459.                 
  460.             }
  461.             if( name0!=0 ){
  462.                 *d++=name0;*d++=name1;
  463.                 cnd=SCH_BOTM;
  464.                 if( *(s+1)=='>' ){
  465.                     cnd=SCH_NAME;
  466.                 }
  467.                 s+=2;
  468.             }
  469.             else{
  470.                 *d++=skip;
  471.             }
  472.         }
  473.         else if( cnd==SCH_BOTM ){
  474.             if( *s=='>' ){
  475.                 cnd=SCH_NAME;
  476.             }
  477.             s++;
  478.             *d++=' ';
  479.         }
  480.     }
  481.     *d++=NULL;
  482.     
  483. }
  484.  
  485.  
  486.  
  487.  
  488. int    FatalErr(e)
  489. unsigned char *e;
  490. {
  491.     printf("ERR:%s\n",e);
  492. }
  493.  
  494.  
  495. int    main(argc,argv)
  496. int    argc;
  497. char    *argv[];
  498. {
  499.     int    res=0;
  500.     FILE    *fp;
  501.  
  502.     if( argc==1 ){
  503.         printf("X68k 着メロコンパイラ(評価版) v0.10 by 電魔団\shoryu 2000\n"
  504.         "usage : @>cmscc *.cms [option]\n"
  505.         "option: /F 対応機種をF502iに(デフォルト)\n"
  506.         "    /P      P501iに\n"
  507.         "    /H      PHS-J80(H\")に\n"
  508.         "    /H      SH811(ドッチーモ)に\n"
  509.         );
  510.         res=-1;
  511.         goto quick_exit;
  512.     }
  513.     
  514.     Telephone=F502I;    //デフォルトは作者が持っているもの
  515.     if( argc==3 ){
  516.         if( argv[2][0]=='-' || argv[2][0]=='/' ){ ; switch( argv[2][1] ){
  517.             case 'f': case 'F':    Telephone=F502I;    break;
  518.             case 'p': case 'P':    Telephone=P501I;    break;
  519.             case 'h': case 'H':    Telephone=HDGE_J80;    break;
  520.             case 's': case 'S':    Telephone=SH811;    break;
  521.         }}
  522.     }
  523.     
  524.     fp=fopen(argv[1],"rt");
  525.     if( fp==NULL ){
  526.         printf("%sが見つかりません\n",argv[1]);
  527.         res=-1;
  528.         goto quick_exit;
  529.     }
  530.     while( feof(fp)==0 ){
  531.         
  532.         fgets(inBuf,BUFSIZE,fp);
  533.         
  534.         res=CMSCC_conv12(inBuf,tmpBuf,mesBuf);
  535.         if( res==READ_REMARK || res==READ_CRLF ){
  536.             //printf("$");
  537.             //読みとばしていい行を読んだ
  538.             continue;
  539.         }
  540.         if( res<0 ){
  541.             FatalErr(mesBuf);
  542.             break;
  543.         }
  544.         //printf("//%s\n",tmpBuf);
  545.         
  546.         switch( Telephone ){
  547.             case F502I:    res=CMSCC_conv23_F502i(tmpBuf,outBuf,mesBuf);    break;
  548.             case P501I:    res=CMSCC_conv23_P501i(tmpBuf,outBuf,mesBuf);    break;
  549.             
  550.             case HDGE_J80:    res=CMSCC_conv23_HDGE_J80(tmpBuf,outBuf,mesBuf);break;
  551.             case SH811:    res=CMSCC_conv23_SH811(tmpBuf,outBuf,mesBuf);    break;
  552.         }
  553.         if( res<0 ){ FatalErr(mesBuf); break; }
  554.         printf("%s\n",outBuf);
  555.         CMSCC_convKANA(outBuf,tmpBuf,mesBuf);
  556.         printf("%s\n",tmpBuf);
  557.     }
  558.     fclose(fp);
  559.  
  560. quick_exit:
  561.     return(res);
  562.  
  563. }
  564.  
  565.  
  566.